package ddd.ajava.chapter2.question1;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import ddd.ajava.util.StringUtil;

/**
 * @author lenovo 
 * 反射得到Person源代码有如下步骤 
 * 1.获得包名 
 * 2.获得类名 
 * 3.获得构造方法
 * 4.获得属性
 * 5.获得方法 
 * 6.组装成为一个类
 */
public class GeneratePerson {
	private static final String BLANK = " ";
	private static final String TAB = "\t";
	private StringBuilder sb = new StringBuilder();

	public static void main(String[] args) {
		GeneratePerson gp = new GeneratePerson();
		gp.generate();
	}
	
	/*private void testModifier(){
		System.out.println(Modifier.PUBLIC);//1
		System.out.println(Modifier.PRIVATE);//2
		System.out.println(Modifier.PROTECTED);//4
		System.out.println(Modifier.INTERFACE);//
	}*/

	private static Class<?> clazz = null;
	static {
		try {
			clazz = Class.forName("ddd.ajava.chapter2.question1.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public void generate(){
		this.getPackageDesc();
		this.getClassDesc();
		this.getFieldDesc();
		this.getConstructorDesc();
		this.getMethodDesc();
		sb.append("\n}");
		this.generateOutput();
	}

	private void getPackageDesc() {
		String packageName = clazz.getPackage().getName();
		sb.append("package "+packageName+".generated;");
	}

	/**
	 * Modifier类修饰符的对应情况
	 * Modifier.PUBLIC //1
	 * Modifier.PRIVATE//2
	 * Modifier.PROTECTED//4
	 * "default"//0
	 * modifier值>=512即为interface，0-511是class
	 */
	private void getClassDesc() {
		String classModifier="";
		int modifier=clazz.getModifiers();
		if(modifier==0){
			classModifier="class";
		}else if(modifier==1){
			classModifier="public class";
		}else{
			if(Modifier.isPublic(modifier)){
				classModifier="public interface";
			}else{
				classModifier="interface";
			}
		}
		String className = clazz.getSimpleName();
		sb.append("\n\n"+classModifier+BLANK+className+"{");
	}

	private void getConstructorDesc() {
		Constructor[] cons = clazz.getDeclaredConstructors();
		for (Constructor c : cons) {
			Class[] param=c.getParameterTypes();
			StringBuilder paramSB=new StringBuilder();
			//有参数的方法，要在类型后面添加变量名
			if(param.length>0){
				paramSB.append(clazz.getSimpleName()+"(");
				String arg="arg";
				for(int i=0;i<param.length;i++){
					paramSB.append(param[i].getCanonicalName()+BLANK+arg+i+",");
				}
				paramSB=new StringBuilder(paramSB.substring(0, paramSB.length()-1));
				paramSB.append(")");
				String name=c.toString();
				name=name.replaceFirst("\\S(\\w*\\.*)*\\((\\w*\\.*\\ *)*\\)",paramSB.toString());
				sb.append("\n"+TAB+name+"{\n\n"+TAB+"}\n");
				continue;
			}
			
			String name=c.toString();
			name=name.replaceFirst("\\S(\\w*\\.*)*\\(", clazz.getSimpleName()+"(");
			sb.append("\n"+TAB+name+"{\n\n"+TAB+"}\n");
		}
	}

	private void getFieldDesc() {
		Field[] field = clazz.getDeclaredFields();
		for (Field f : field) {
			String name=f.toString();
			name=name.replaceFirst("\\S(\\w*\\.*)*$", f.getName());
			sb.append("\n"+TAB+name+";");
		}
		sb.append("\n");
	}

	private void getMethodDesc() {
		Method[] method = clazz.getDeclaredMethods();
		for (Method m : method) {
			Class[] param=m.getParameterTypes();
			StringBuilder paramSB=new StringBuilder();
			//有参数的方法，要在类型后面添加变量名
			if(param.length>0){
				paramSB.append(m.getName()+"(");
				String arg="arg";
				for(int i=0;i<param.length;i++){
					paramSB.append(param[i].getCanonicalName()+BLANK+arg+i+",");
				}
				paramSB=new StringBuilder(paramSB.substring(0, paramSB.length()-1));
				paramSB.append(")");
				String name=m.toString();
				name=name.replaceFirst("\\S(\\w*\\.*)*\\((\\w*\\.*\\ *)*\\)",paramSB.toString());
				sb.append("\n"+TAB+name+"{\n\n"+TAB+"}\n");
				continue;
			}
			
			String name=m.toString();
			name=name.replaceFirst("\\S(\\w*\\.*)*\\(",m.getName()+"(");
			//获得return语句
			String attrName=StringUtil.firstCharToLower(m.getName().substring(3));
			paramSB.append("\n"+TAB+TAB+"return "+attrName+";");
			
			sb.append("\n"+TAB+name+"{");
			sb.append(paramSB.toString()+"\n"+TAB+"}\n");
		}
	}

	private void generateOutput() {
		String path = clazz.getPackage().getName();
		path = path.replace(".", "\\");
		String url = System.getProperty("user.dir") + "\\src\\" + path + "\\generated\\"
				+ clazz.getSimpleName()+ ".java";
		FileOutputStream fileWriter;
		try {
			fileWriter = new FileOutputStream(url);
			fileWriter.write(sb.toString().getBytes("UTF-8"));
			fileWriter.flush();
			fileWriter.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
